package spring.framework.context.annotation;

import cn.hutool.core.util.StrUtil;
import spring.framework.beans.factory.config.BeanDefinition;
import spring.framework.beans.factory.support.BeanDefinitionRegistry;
import spring.framework.stereotype.Component;

import java.util.Set;

/**
 * @author pengzh
 * @desc
 * @class ClassPathBeanDefinitionScanner
 * @since 2021-11-25
 */
public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider {

    private BeanDefinitionRegistry registry;

    public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
        this.registry = registry;
    }


    /**
     * 扫描组件并解析作用域后注册
     */
    public void doScan(String... basePackages) {
        for (String basePackage : basePackages) {
            Set<BeanDefinition> candidateComponents = findCandidateComponents(basePackage);
            for (BeanDefinition beanDefinition : candidateComponents) {
                String scope = resovleScope(beanDefinition);
                if (StrUtil.isNotBlank(scope)) {
                    beanDefinition.setScope(scope);
                }
                registry.registerBeanDefinition(determineBeanName(beanDefinition), beanDefinition);
            }
        }
    }

    /**
     * 解析作用域
     */
    public String resovleScope(BeanDefinition beanDefinition) {
        Class<?> beanClass = beanDefinition.getBeanClass();
        Scope scope = beanClass.getAnnotation(Scope.class);
        if (scope != null) {
            return scope.value();
        }
        return StrUtil.EMPTY;
    }

    /**
     * 推断beanName
     */
    public String determineBeanName(BeanDefinition beanDefinition) {
        Class<?> beanClass = beanDefinition.getBeanClass();
        Component component = beanClass.getAnnotation(Component.class);
        String value = component.value();
        if (StrUtil.isBlank(value)) {
            return StrUtil.lowerFirst(beanClass.getSimpleName());
        }
        return value;
    }

}
